<template>
  <div class="tip" id="tip">测试悬浮框</div>
  <!-- <p class="top-info">网格标绘系统</p> -->
  <el-row type="flex">
    <div class="column-wrap">
      <div style="color: green" class="tag">功能测试:</div>
      <el-button @click="runCamera">移动镜头</el-button>
      <el-button @click="runRotate">旋转</el-button>
      <el-button @click="add2group">添加到组</el-button>
      <el-button @click="removeFromGroup">组中删除</el-button>
      <el-button @click="testUndo">撤销恢复</el-button>
      <el-select @change="setLineStyle" placeholder="曲线样式">
        <el-option label="直线连接" :value="1"></el-option>
        <el-option label="折线连接" :value="2"></el-option>
        <el-option label="曲线连接" :value="3"></el-option>
      </el-select>
      <el-button @click="doAdsorption" :type="cbAdsorption ? 'primary' : ''">b:辅助线吸附</el-button>
      <el-button @click="runControlPoint" :type="cbTransform ? 'primary' : ''">b:控制点</el-button>
      <el-button @click="toFixed" :type="isFixed ? 'primary' : ''">b:固定定位</el-button>
      <el-button @click="exchangeSelectArea" :type="isSelectArea ? 'primary' : ''">b:绘制区域--{{
        blocksInArea
      }}</el-button>
      <el-button @click="toCenter">居中对齐</el-button>
      <el-select @change="drawBlock" placeholder="绘制元素">
        <el-option label="绘制矩形" value="rect"></el-option>
        <el-option label="绘制三角形" value="triangle"></el-option>
        <el-option label="绘制图片" value="image"></el-option>
        <el-option label="绘制文字" value="text"></el-option>
        <el-option label="绘制线段" value="line"></el-option>
        <el-option label="绘制多边形" value="polygon"></el-option>
        <el-option label="绘制箭头" value="arrow"></el-option>
      </el-select>
      <el-button @click="getGridCoordByClick">自动寻路</el-button>
      <el-select @change="animateEffect" placeholder="动画效果">
        <el-option label="暴击特效" value="1"></el-option>
        <el-option label="兵力减少" value="2"></el-option>
      </el-select>
      <el-button @click="toScroll">向下滚动</el-button>
    </div>
    <canvas id="myCanvas" width="1200" height="700"></canvas>
    <el-collapse v-model="activeName" accordion style="min-width: 270px;padding-left: 20px;">
      <el-collapse-item title="Feedback" name="0">
        <template #title>
          <div style="color: #8e44ad" class="tag">待开发:</div>
          <el-icon class="header-icon">
            <info-filled />
          </el-icon>
        </template>
        <ul class="bug-wrap">
          <!-- <li>画布放大缩小移动增加过渡效果</li> -->
          <li>线性元素拖拽会重定位, 线性元素选取困难</li>
          <li>缩放按比例</li>
          <li>元素间对齐吸附</li>
          <li>缩略图</li>
        </ul>
      </el-collapse-item>
      <el-collapse-item title="Consistency" name="1">
        <template #title>
          <div style="color: red" class="tag">bug记录:</div>
          <el-icon class="header-icon">
            <info-filled />
          </el-icon>
        </template>
        <ul class="bug-wrap">
          <li>旋转后的坐标点变化导致形变有问题</li>
          <!-- <li>同时多个drawlinegrid方法会性能卡顿</li> -->
          <li>保存本地画布会重复数据</li>
          <!-- <li>多个元素撤销会有问题</li> -->
          <!-- <li>旋转动画会导致辅助线不出现</li> -->
          <li>线性元素需要加入到撤销删除栈中</li>
          <li>不规则图形的碰撞检测</li>
        </ul>
      </el-collapse-item>
      <el-collapse-item title="Feedback" name="2">
        <template #title>
          <div style="color: green" class="tag">已实现:</div>
          <el-icon class="header-icon">
            <info-filled />
          </el-icon>
        </template>
        <ul class="bug-wrap">
          <div style="color: red" class="tag"></div>
          <li> 网格拖拽</li>
          <li> 元素在网格上,且随网格移动,有一套相对坐标系统</li>
          <li> 元素可通过控制点放大缩小旋转</li>
          <li> 元素可拖拽,也可通过暴露的api移动,有过渡动画</li>
          <li> 元素可以是系统自带的长方形,三角形,多点的线段,或自定义图片,自定义文字</li>
          <li> 支持绘制自定义块状元素,暴露上下文,x,y宽高等信息</li>
          <li> 元素拖拽的辅助线吸附效果</li>
          <li> 元素可以分组,同一组元素拖拽,组内元素会跟着移动</li>
          <li> 操作的撤销恢复操作</li>
          <li> 键盘事件组合键的封装</li>
          <li> 以鼠标中心点去放大缩小</li>
          <li> 元素具有层级,可调整谁覆盖谁</li>
          <li> 画布放大可以任意点为中心点放大缩小</li>
          <li> 主文件有暴露增删改查等通用api</li>
          <li> 元素点击后获取焦点样式</li>
          <li> 支持绘制区域选择区域内的元素</li>
          <li> 支持元素间连线效果, 连线样式可选择,直线,折线或曲线</li>
          <li> 屏幕外的元素不绘制</li>
          <li> 元素旋转后的顶点坐标可以计算获取</li>
          <li> 可设置固定定位,不跟随画布移动</li>
          <li> 可类似于html元素嵌套元素,子元素跟随父元素移动</li>
          <li> 简单的矩形碰撞检测</li>
          <li> 可以网格单元为相对单位定位,默认是以相对像素大小定位</li>
          <li> 增加自动寻路功能,寻找一点到另一点的最短路径</li>
          <li> 右下角有比例尺展示</li>
        </ul>
      </el-collapse-item>
    </el-collapse>
  </el-row>
  <div id="myChart" style="width: 300px;height:250px;"></div>
</template>
<script lang="ts">
import { onBeforeMount, onMounted, watch, reactive, ref } from "vue";
import TreeLayout from "./layout/TreeLayout";
import Group from "./Group";
import GridSystem from "./GridSystem";
import { MyRect, MyLine, MyText, Block, MyMark, MyPolygon, MyCircle, MyCustom } from "./Index";
import { ElMessage } from "element-plus";
import Link from "./Link";
import { CoordinateSystem, FontFamily, LinkMark, LinkStyle, MyEvent, } from "./Constants";
import Shortcuts from "./Shortcuts";
import PathSearch from "./PathSearch";
import gsap from 'gsap'
import CustomEase from 'gsap/CustomEase'
import * as echarts from 'echarts';
import { getRandomChineseWord } from "./utils"

export default {
  setup(props: any, context: any) {
    const activeName = ref("0");
    var lineStyle = ref(1);
    var gls: GridSystem; // 响应式用ref包裹
    var cbAdsorption = ref(GridSystem.cbAdsorption);
    var cbTransform = ref(GridSystem.cbTransform);
    var isSelectArea = ref(GridSystem.isSelectArea);
    var isFixed = ref(false);
    var blocksInArea = ref(0);
    let line1: Link;
    let line2: Link;
    let line3: Link;
    let line4: Link;
    let rect2: Block;
    let rectGrid: Block;
    document.addEventListener(MyEvent.DRAW_AREA, (e: any) => {
      blocksInArea.value = e.detail.length;
    });
    var rectGroup = new Group();
    var offsetY = 0;
    let textArr: string[] = [];
    for (let index = 0; index < 20; index++) {
      let text = []
      for (let order = 0; order < 30; order++) {
        text.push(getRandomChineseWord())
      }
      textArr.push(text.join(""))
    }

    onMounted(() => {

      let myCanvas = document.querySelector("#myCanvas");
      if (myCanvas) {
        gls = new GridSystem(myCanvas as HTMLCanvasElement);
      }

      // 直线与多边形测试拖拽
      let line = new MyLine([
        { x: 130, y: 130 },
        { x: 200, y: 200 },
      ])
      let line7 = new MyPolygon([
        { x: 350, y: 150 },
        { x: 380, y: 150 },
        { x: 365, y: 175 },
      ])
      gls.add(line);
      gls.add(line7);

      // 自绘制元素
      let customFt = new MyCustom(100, 170, 4, 4, (ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) => {
        ctx.moveTo(x, y);
        ctx.lineTo(x + width, y + height);
        ctx.moveTo(x + width, y);
        ctx.lineTo(x, y + height);
        ctx.fillStyle = "#000"
        ctx.stroke();
      });

      let customLabel = new MyText("自绘制元素", -1.7, -2.3, 1.5, 1.5);
      customLabel.fill = "#000";
      customFt.addBlock(customLabel)
      gls.add(customFt)

      // 裁剪模仿填充
      let customFt2 = new MyCustom(250, 100, 35, 10, (ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) => {
        ctx.save();
        ctx.moveTo(x, y);
        ctx.lineTo(x + width, y);
        ctx.lineTo(x + width, y + height);
        ctx.lineTo(x, y + height);
        ctx.closePath();
        ctx.fillStyle = "#000"
        ctx.stroke();
        // 剪裁
        ctx.clip();
        for (let index = 0; index < textArr.length; index++) {
          ctx.font = `15px ${FontFamily.HEITI}`;
          ctx.fillText(textArr[index], x, y + index * 20 - offsetY);
        }
        ctx.restore();
      });

      let customLabel2 = new MyText("滚动条", 3, -2.3, 1.5, 1.5);
      customLabel2.fill = "#000";
      customFt2.addBlock(customLabel2)
      gls.add(customFt2)

      // 滚动条
      let customFt3 = new MyCustom(250, 170, 15, 10, (ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) => {
        ctx.save();
        ctx.moveTo(x, y);
        ctx.lineTo(x + width, y);
        ctx.lineTo(x + width, y + height);
        ctx.lineTo(x, y + height);
        ctx.closePath();
        ctx.fillStyle = "#000"
        ctx.stroke();
        // 剪裁
        ctx.clip();

        ctx.fillStyle = '#389e0d';
        for (let index = 0; index < height / 25; index++) {
          for (let order = 0; order < width / 25; order++) {
            ctx.beginPath();
            ctx.arc(x + order * 30, y + index * 30, 10, 0, Math.PI * 2, false);
            ctx.fill();
          }
        }
        ctx.restore();
      });

      let customLabel3 = new MyText("裁剪模仿填充", 3, -2.3, 1.5, 1.5);
      customLabel3.fill = "#000";
      customFt3.addBlock(customLabel3)
      gls.add(customFt3)

      // // gif 动图
      // let gifImg = gls.createImage(
      //   { x: 0, y: 0, width: 110, height: 100 },
      //   `/bird/${1}.gif`
      // );
      // let index = 1;
      // (function gif() {
      //   requestAnimationFrame(() => {
      //     if (index % 1 === 0) {  // 判断是不是整数
      //       gifImg.setSrc(`/bird/${index}.gif`)
      //     }
      //     if (index >= 52) {
      //       index = 1;
      //     }
      //     index += 0.5;  // 控制播放速度
      //     gif();
      //   });
      // })()

      // // 固定定位,背景图
      // let fixedImg = gls.createImage(
      //   { x: 0, y: 0, width: 1000, height: 800 },
      //   "/map.png"
      // );
      // fixedImg.cbSelect = false;
      // fixedImg.cbMove = false;

      // // 层级嵌套
      // let rect0 = gls.createRect({ x: 0, y: 0, width: 100, height: 100 });
      // let rectSon = new MyRect(0, 0, 7, 7);
      // rectSon.fill="yellow";
      // let rectSonSon = new MyText("层层嵌套的子元素", 0, 0, 2, 2);
      // rectSonSon.fill="#000";
      // rectSon.addBlock(rectSonSon)
      // rect0.addBlock(rectSon)

      // // html联动
      // let tip = document.getElementById("tip");
      // if (gls.focusNode) {
      //   gls.focusNode.mouseOn = function (e: any) {
      //     if (tip) {
      //       tip.style.left = e.clientX + "px";
      //       tip.style.top = e.clientY - 50 + "px";
      //     }
      //   };
      //   gls.focusNode.mouseLeave = function () {
      //     if (tip) {
      //       tip.style.left = 0 + "px";
      //       tip.style.top = 0 + "px";
      //     }
      //   };
      // }

      // 基于准备好的dom，初始化echarts实例
      var myChart = echarts.init(document.getElementById('myChart'));
      // 绘制图表
      myChart.setOption({
        xAxis: {
          data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
        },
        yAxis: {},
        series: [
          {
            name: '销量',
            type: 'bar',
            data: [5, 20, 36, 10, 10, 20]
          }
        ],
        grid: {
          left: "12%",
          top: "8%",
          right: "5%",
          bottom: "10%"
        },
      });

      myChart.on('finished', _ => {
        var img1 = new Image();
        img1.src = myChart.getDataURL({
          pixelRatio: 2,
          backgroundColor: 'transparent'
        });
        img1.onload = () => {
          let customFt = new MyCustom(300, -20, 30, 21, (ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) => {
            ctx.drawImage(img1, x, y, width, height)
          });
          let customLabel = new MyText("自绘制元素", 11, -2.3, 1.5, 1.5);
          customLabel.fill = "#000";
          customFt.addBlock(customLabel)
          gls.add(customFt)

          // 动画旋转
          let rect1 = gls.createRect({ x: 260, y: 10, width: 50, height: 50 });
          rect1.borderRadius = 200
          rect1.fill = "red";
          rect1.angle = 45;
          rotate();
          function rotate() {
            requestAnimationFrame(() => {
              rect1.angle++;
              // gls.drawLineGrid();
              rotate();
            });
          }

          // 关系树
          let arrow = gls.createArrow({
            x: 100,
            y: 100,
            width: 10,
            height: 15,
            cbTransform: false,
          });
          arrow.linkMark = LinkMark.END;
          arrow.zIndex = 10;
          arrow.isBindLink = true;

          let arrow2 = gls.createArrow({
            x: 100,
            y: 100,
            width: 10,
            height: 15,
            cbTransform: false,
          });
          arrow2.linkMark = LinkMark.END;
          arrow2.zIndex = 10;
          arrow2.isBindLink = true;

          rect2 = gls.createRect({ x: 360, y: 150, width: 50, height: 50 });
          // let rect5 = gls.createRect({ x: 560, y: 250, width: 50, height: 50 });
          rect2.mouseDown = () => {
            ElMessage.info("诶呀,被点到啦~");
          }
          let rect3 = gls.createImage(
            { x: 260, y: 150, width: 50, height: 50 },
            "/qizhi.png"
          );
          let rect4 = gls.createText(
            { x: 100, y: 150, width: 100, height: 50 },
            "测试文字"
          );
          line1 = new Link(rect1, rect2, LinkStyle.CURVE);
          let label = new MyText("线段的子元素", 0, 0, 1.5, 1.5);
          label.fill = "#000"
          label.background = "#fff";
          line1.addBlock(label);
          line1.arrows.push(arrow);
          line2 = new Link(rect1, rect3, LinkStyle.CURVE);
          line3 = new Link(rect1, rect4, LinkStyle.CURVE);
          line4 = new Link(rect2, customFt, LinkStyle.CURVE);
          line4.arrows.push(arrow2);
          gls.add(line1);
          gls.add(line2);
          gls.add(line3);
          gls.add(line4);
        }
      })

      // // new TreeLayout();

      // 草地
      // let cdGrid = new MyRect(0, 0, 4*CoordinateSystem.GRID_SIZE, 4*CoordinateSystem.GRID_SIZE);
      // cdGrid.loadTexture();
      // gls.add(cdGrid);

      let img = new Image();
      img.src = "/cd.png";
      img.onload = () => {
        // for (let index = 0; index < 100; index++) {
        //   let cdGrid = new MyMark(null, 0, 0, 4 * CoordinateSystem.GRID_SIZE, 4 * CoordinateSystem.GRID_SIZE);
        //   cdGrid.setGridCoord(1 + index * 4, 1);
        //   cdGrid.img = img;
        //   cdGrid.cbSelect = false;
        //   gls.add(cdGrid);
        // }

        // // 网格单位定位,自动寻路
        // rectGrid = new MyMark("/曹昂.png", 0, 0, 4, 4);
        // rectGrid.setGridCoord(4, 4);
        // let name = new MyText("曹昂", 0.5, -2, 1.5, 1.5);
        // name.fill = "#000";
        // name.fontFamily = FontFamily.SONGTI;
        // rectGrid.addBlock(name)
        // gls.add(rectGrid);

        // for (let index = 0; index < 6; index++) {
        //   let rectGrid1 = new MyMark("/jztx.png", 0, 0, 4, 4);
        //   rectGrid1.setGridCoord(2 + index, 7);
        //   rectGrid1.isObstacle = true;
        //   // rectGrid1.cbSelect = false;
        //   gls.add(rectGrid1);
        // }

      }

      // 键盘控制
      // new Shortcuts(["UP"], () => {
      //   rectGrid.y -= 16;
      //   // gls.drawLineGrid();
      // });
      // new Shortcuts(["DOWN"], () => {
      //   rectGrid.y += 16;
      //   // gls.drawLineGrid();
      // });
      // new Shortcuts(["left"], () => {
      //   rectGrid.x -= 16;
      //   // gls.drawLineGrid();
      // });
      // new Shortcuts(["right"], () => {
      //   rectGrid.x += 16;
      //   // gls.drawLineGrid();
      // });

    });

    function toScroll() {
      offsetY += 5;
    }

    function getGridCoordByClick() {
      ElMessage.info("点击某个单元格作为目标地点!");
      document.addEventListener("mousedown", findPath);
    }

    function soldierMinus() {
      let minus = new MyText("-1000", 5.5, 2, 1.5, 1.5);
      minus.fill = "red";
      gsap.to(minus, {
        duration: 1.25,
        x: 5.5,
        y: -2,
        opacity: 0,
        ease: "slow.out",
        onUpdate(e) {
          minus.fill = `rgba(220,20,60, ${minus.opacity})`;
        },
        onComplete() {
          rectGrid.popBlock()
        }
      })
      rectGrid.addBlock(minus)
    }

    function animateEffect(value: any) {
      switch (value) {
        case "1":
          strongAttack();
          break;
        case "2":
          soldierMinus();
          break;
        default:
          break;
      }
    }

    function strongAttack() {
      var mp3Url = "/music/duang.mp3";
      var player = new Audio(mp3Url);
      player.play();

      let baoji = new MyMark("/暴击.png", gls.canvasWidth - 100, gls.canvasHeight / 2 - 100, 200, 200);
      baoji.isFixedPos = true;
      baoji.isFixedSize = true;
      baoji.cbSelect = false;

      gsap.to(baoji, {
        duration: 1.25,
        x: -200,
        y: gls.canvasHeight / 2 - 100,
        onUpdate() {
          // // gls.drawLineGrid();
        },
        ease: CustomEase.create("custom", "M0,0 C0.083,0.294 0.696,0.422 0.828,0.542 0.932,0.768 0.752,1 1,1 "),
      })
      gls.add(baoji);

    }

    function findPath(e: any) {
      if (!rectGrid) {
        ElMessage.warning("请先选中一个元素");
        return;
      }
      let gridPoint = gls.getGridCoordByClick(e);
      let rectGrid1 = new MyRect(0, 0, 4, 4);
      rectGrid1.setGridCoord(gridPoint.x, gridPoint.y);
      gls.add(rectGrid1);

      let pathFind = new PathSearch(
        {
          x: rectGrid.gridCoord.x,
          y: rectGrid.gridCoord.y,
        },
        gridPoint
      );
      pathFind.pushNearNode(() => pathFind.run2Target(rectGrid));
      document.removeEventListener("mousedown", findPath);
    }

    function runCamera() {
      gls.toSomeWhere({ x: 100, y: 100 }, 1000);
    }

    function doAdsorption() {
      gls.setConfigs({
        cbAdsorption: !GridSystem.cbAdsorption,
      });
      cbAdsorption.value = GridSystem.cbAdsorption;
      // gls.drawLineGrid();
    }

    function runControlPoint() {
      gls.setConfigs({
        cbTransform: !GridSystem.cbTransform,
      });
      cbTransform.value = GridSystem.cbTransform;
      // gls.drawLineGrid();
    }

    function runRotate() {
      if (gls.focusNode) {
        gls.focusNode.angle += 45;
        // gls.drawLineGrid();
      } else {
        ElMessage.warning("请先选中一个元素");
      }
    }

    function testUndo() {
      ElMessage.info("用快捷键ctrl+z, ctrl+y");
    }

    function drawBlock(val: string) {
      ElMessage.info(
        "点击屏幕绘制吧,普通元素点击一下, 线段需要连续点击,且双击结束"
      );
      gls.clickDrawBlock(val, 200, 200, "/qizhi.png");
    }

    function add2group() {
      if (gls.focusNode) {
        rectGroup.add(gls.focusNode);
        ElMessage.success("添加成功");
      } else {
        ElMessage.warning("请先选中一个元素");
      }
    }

    function removeFromGroup() {
      if (gls.focusNode) {
        rectGroup.remove(gls.focusNode);
        ElMessage.success("移出成功");
      } else {
        ElMessage.warning("请先选中一个元素");
      }
    }

    function exchangeSelectArea() {
      GridSystem.isSelectArea = !GridSystem.isSelectArea;
      isSelectArea.value = GridSystem.isSelectArea;
      if (GridSystem.isSelectArea) ElMessage.success("点击绘制吧!");
      // gls.drawLineGrid();
    }

    function toCenter() {
      if (gls.focusNode) {
        gls.toCenter(gls.focusNode);
      } else {
        ElMessage.warning("请先选中一个元素");
      }
    }

    function setLineStyle(val: number) {
      lineStyle.value = val;
      switch (lineStyle.value) {
        case 1:
          line1.connectStyle = LinkStyle.STRAIGHT;
          line2.connectStyle = LinkStyle.STRAIGHT;
          line3.connectStyle = LinkStyle.STRAIGHT;
          break;
        case 2:
          line1.connectStyle = LinkStyle.BROKEN;
          line2.connectStyle = LinkStyle.BROKEN;
          line3.connectStyle = LinkStyle.BROKEN;
          break;
        case 3:
          line1.connectStyle = LinkStyle.CURVE;
          line2.connectStyle = LinkStyle.CURVE;
          line3.connectStyle = LinkStyle.CURVE;
          break;
        default:
          break;
      }
      // gls.drawLineGrid();
    }

    function toFixed() {
      isFixed.value = !isFixed.value;
      if (gls.focusNode) {
        if (isFixed.value) {
          gls.focusNode.toFixedPos();
          gls.focusNode.toFixedSize();
        } else {
          gls.focusNode.toRelativePos();
          gls.focusNode.toRelativeSize();
        }
      } else {
        ElMessage.warning("请先选中一个元素");
      }
    }

    return {
      activeName,
      setLineStyle,
      runCamera,
      doAdsorption,
      runRotate,
      runControlPoint,
      testUndo,
      drawBlock,
      cbAdsorption,
      cbTransform,
      isSelectArea,
      blocksInArea,
      add2group,
      removeFromGroup,
      exchangeSelectArea,
      toCenter,
      isFixed,
      toFixed,
      getGridCoordByClick,
      strongAttack,
      soldierMinus,
      animateEffect,
      toScroll,
    };
  },
};
</script>

<style scoped lang="less">
#myCanvas {
  border: 1px solid Olive;
}

.read-the-docs {
  color: #888;
}

.bug-wrap {
  display: flex;
  flex-flow: column;
  text-align: left;
  counter-reset: li;
  width: 270px;
  max-height: 500px;
  overflow: auto;
  font-size: 15px;

  li:before {
    content: counter(li) + ".";
    counter-increment: li;
  }
}

.column-wrap {
  width: 100px;
  padding-right: 20px;
  display: flex;
  flex-flow: column;

  .el-button,
  .el-input,
  div {
    width: 100%;
    margin: 10px;
    margin-top: 0;
  }
}

.tip {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 10;
  background: #bae0ff;
  border: 1px solid;
  padding: 0 4px;
  // transition: .1s;
}

.top-info {
  text-align: center;
  font-size: 22px;
}

::v-deep .el-collapse-item__header {
  height: 38px;
  line-height: 38px;
}

.tag {
  display: inline-block;
  font-weight: bolder;
}
</style>
